﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using yq.IBase;
using yq.IBase.DBHelper;
using yq.IBase.Basis;
using System.Reflection;
using cn.Util;

namespace yq.IBase.Basis
{
    /// <summary>
    /// 缓存基础对象 ，一般model继承这个对象
    /// 继承关系 DbModelBase=> ModelBase
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class ModelBase<T> : IModelBase where T : ModelBase<T>, new()
    {
        /// <summary>
        /// 字段列表 （内部）
        /// </summary>
        /// <returns></returns>
        protected internal abstract List<string> GetColumns();

        /// <summary>
        /// 表名，默认表名（内部）
        /// 当水平切割时不要使用
        /// </summary>
        /// <returns></returns>
        protected internal abstract string GetTableName();

        /// <summary>
        /// 主键（内部）
        /// </summary>
        /// <returns></returns>
        protected internal string GetTableKey()
        {
            return GetColumns()[0];
        }


        /// <summary>
        /// 语句缓存
        /// </summary>
        protected static SQLCache sqlString = new SQLCache();

        /// <summary>
        /// 实体类赋值
        /// </summary>
        /// <param name="info">对象实体</param>
        /// <param name="row">数据行,应为全体字段记录</param>
        protected internal abstract void SetValue(T info, DataRow row);

        /// <summary>
        /// 写入主键值
        /// </summary>
        public abstract void SetKeyValue(dynamic id);

        /// <summary>
        /// 获取主键值
        /// </summary>
        public abstract dynamic GetKeyValue();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="comm"></param>
        /// <param name="info"></param>
        /// <param name="cn"></param>
        protected internal abstract void GetDbParameters(System.Data.Common.DbCommand comm, T info, DbHelper cn);

        /// <summary>
        /// 获取列表IList
        /// </summary>
        /// <param name="rows">数据行组,应为全体字段记录</param>
        /// <returns>返回IList对象列表</returns>
        public IList<T> GetIList(DataTable dt)
        {
            IList<T> lists = new List<T>();
            if (dt == null) return lists;
            foreach (DataRow dr in dt.Rows)
            {
                T info = new T();
                SetValue(info, dr);
                lists.Add(info);
            }

            return lists;
        }

        /// <summary>
        /// 获取列表IList
        /// </summary>
        /// <param name="dt">数据集DataTable,应为全体字段记录</param>
        /// <returns>返回IList对象列表</returns>
        protected internal PageList<T> GetPageList(DataTable dt)
        {
            PageList<T> lists = new PageList<T>();

            if (dt == null) return lists;
            foreach (DataRow dr in dt.Rows)
            {
                T info = new T();
                SetValue(info, dr);
                lists.Add(info);
            }

            return lists;
        }

        /// <summary>
        /// 根据主键获取选择性的SQL语句
        /// </summary>
        /// <param name="aat_id">主键值</param>
        /// <returns></returns>
        protected internal virtual string GetSelectKey(string id)
        {
            var sql = GetSelectSql();
            sql.WhereString = " Where " + GetTableKey() + " = @id ";

            return sql.toSql();
        }

        /// <summary>
        /// 根据主键获取选择性的SQL语句
        /// </summary>
        /// <param name="aat_id">主键值</param>
        /// <returns></returns>
        protected internal virtual string GetSelectKey(IList<string> id)
        {
            string strid = string.Join("','", id);
            var sql = GetSelectSql();
            sql.WhereString = " Where " + GetTableKey() + " in ('" + strid + "')";

            return sql.toSql();
        }

        /// <summary>
        /// 返回Select所有字段的SQL语句,不带From
        /// </summary>
        /// <returns></returns>
        protected internal string GetSelectColumns()
        {
            if (string.IsNullOrEmpty(sqlString.Select))
            {
                StringBuilder sql = new StringBuilder();
                foreach (var info in GetColumns())
                {
                    if (sql.ToString().Length == 0)
                    {
                        sql.Append(info);
                    }
                    else
                    {
                        sql.Append("," + info);
                    }
                }
                sqlString.Select = sql.ToString();
            }

            return sqlString.Select;
        }

        /// <summary>
        /// 返回Insert所有字段的SQL语句
        /// </summary>
        /// <returns></returns>
        protected internal string GetInsertColumns(string tableName = null)
        {
            if (string.IsNullOrEmpty(sqlString.Insert))
            {
                StringBuilder sql = new StringBuilder();
                StringBuilder sqlInsert = new StringBuilder();
                StringBuilder sqlValues = new StringBuilder();

                foreach (var code in GetColumns())
                {
                    if (sqlInsert.ToString().Length == 0)
                    {
                        sqlInsert.Append(code);
                    }
                    else
                    {
                        sqlInsert.Append("," + code);
                    }

                    if (sqlValues.ToString().Length == 0)
                    {
                        sqlValues.Append("@" + code);
                    }
                    else
                    {
                        sqlValues.Append(",@" + code);
                    }
                }
                sql.Append(" Insert Into " + (tableName ?? GetTableName()) + "(");
                sql.Append(sqlInsert.ToString());
                sql.Append(") Values(");
                sql.Append(sqlValues.ToString());
                sql.Append(")");

                sqlString.Insert = sql.ToString();
            }

            return sqlString.Insert;
        }

        /// <summary>
        /// 返回Update所有字段的SQL语句
        /// </summary>
        /// <returns></returns>
        protected internal string GetUpdateColumns(string tableName = null)
        {
            if (string.IsNullOrEmpty(sqlString.Update))
            {
                StringBuilder sql = new StringBuilder();
                sql.Append(" Update " + (tableName ?? GetTableName()) + " Set ");

                StringBuilder sqlInsert = new StringBuilder();
                foreach (var code in GetColumns())
                {
                    if (code != GetTableKey())
                    {
                        if (sqlInsert.ToString().Length == 0)
                        {
                            sqlInsert.Append(code + "=@" + code);
                        }
                        else
                        {
                            sqlInsert.Append("," + code + "=@" + code);
                        }
                    }
                }
                sql.Append(sqlInsert.ToString());

                sql.Append(" Where " + GetTableKey() + "=@" + GetTableKey());

                if (GetColumns().Count(obj => obj == "version") != 0)
                {
                    //版本号验证
                    sql.Append(" and Version=@_versionOdl ");
                }

                sqlString.Update = sql.ToString();
            }

            return sqlString.Update;
        }



        /// <summary>
        /// 返回Select 的Where之前(不带where关键字)的SQL语句
        /// </summary>
        /// <param name="sqlWhere">SQL条件,必须从where开始,可以为空</param>
        /// <param name="tableName">指定表名，水平切割用。默认使用GetTableName()的结果</param>
        /// <returns></returns>
        protected internal SelectSQL GetSelectSql(SelectSQL sql=null)
        {
            if (sql == null)
            {
                sql=new SelectSQL();
            }
            sql.Field = GetSelectColumns();
            sql.Table = string.IsNullOrEmpty(sql.Table) ? GetTableName() : sql.Table;

            return sql;
        }

        /// <summary>
        /// 返回Select count(1) 的Where之前(不带where关键字)的SQL语句
        /// </summary>
        /// <param name="sqlWhere">SQL条件,必须从where开始,可以为空</param>
        /// <returns></returns>
        protected internal SelectSQL GetSelectCountSql(SelectSQL sql)
        {
            if (string.IsNullOrEmpty(sql.Table))
            {
                sql.Table = GetTableName();
            }
            sql.Field = " count(1) ";

            return sql;
        }

        /// <summary>
        /// 让model 不需要实例化也能调用
        /// </summary>
        public static T Static
        {
            get
            {
                return new T();
            }
        }

        /// <summary>
        /// 加载数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isdb"></param>
        /// <returns></returns>
        public T Load(string id, DbHelper db = null)
        {
            T t = new T();
            try
            {
                db = db ?? new DbHelper();
                var cm = db.GetSqlStringCommond(t.GetSelectKey(id));
                db.AddInParameter(cm, "id", DbType.String, id);
                DataTable dt = db.ExecuteDataTable(cm);
                if (dt.Rows.Count != 0)
                {
                    t.SetValue(t, dt.Rows[0]);
                }
             
            }
            finally
            {
                db.Close();
                db.Dispose();
            }

            return t ?? new T();
        }



    }


    /// <summary>
    /// sql语句缓存
    /// </summary>
    public class SQLCache
    {
        public string Insert { get; set; }

        public string Update { get; set; }

        public string Select { get; set; }

        public string TableName { get; set; }

        public string TableKye { get; set; }
    }



    

}
